package download;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

class Logger extends Thread {
    /** 下载的文件的名字 */
    private final Properties log;
    private final File file;
    private final AtomicBoolean canceled = new AtomicBoolean(true);

    Logger(String storageLocation, String url, int threadCount) {
        String logFileName = storageLocation + ".log";
        boolean reStart = Files.exists(Paths.get(logFileName));
        this.file = new File(logFileName);
        this.log = new Properties();
        if (reStart) {
            try (FileInputStream fis = new FileInputStream(file)) {
                log.load(fis);
            } catch (IOException ignore) {}
        } else {
            log.put("url", url);
            log.put("wroteSize", "0");
            log.put("threadCount", String.valueOf(threadCount));
            for (int i = 0; i < threadCount; i++) {
                log.put("thread_" + i, "0-0");
            }
        }
    }

    synchronized void updateLog(int threadId, long length, long lowerBound, long upperBound) {
        log.put("thread_" + threadId, lowerBound + "-" + upperBound);
        log.put("wroteSize", String.valueOf(length + Long.parseLong(log.getProperty("wroteSize"))));
    }

    /**
     * 获取区间信息
     *      ret[i][0] = threadID, ret[i][1] = lowerBoundID, ret[i][2] = upperBoundID
     * @return
     */
    long[][] getBounds() {
        long[][] bounds = new long[Integer.parseInt(log.get("threadCount").toString())][3];
        int[] index = {0};
        log.forEach((k, v) -> {
            String key = k.toString();
            if (key.startsWith("thread_")) {
                String[] interval = v.toString().split("-");
                bounds[index[0]][0] = Long.parseLong(key.substring(key.indexOf("_") + 1));
                bounds[index[0]][1] = Long.parseLong(interval[0]);
                bounds[index[0]++][2] = Long.parseLong(interval[1]);
            }
        });
       return bounds;
    }

    long getWroteSize() {
        return Long.parseLong(log.getProperty("wroteSize"));
    }

    @Override
    public void run() {
        while (canceled.get()) {
            try (FileOutputStream fos = new FileOutputStream(file)) {
                log.store(fos, null);
            } catch (IOException ignore) {}
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException ignore) {}
        }
    }

    void close() {
        canceled.set(false);
    }

    void clean() {
        try {
            Files.delete(Paths.get(file.getAbsolutePath()));
        } catch (IOException ignore) {}
    }
}
